<template>
  <div class="data-tree-box">
    <div class="data-tree-box-op">
      <div class="item">
        <a-checkbox :model-value="dataExpand" @change="expandChange"
          >展开/折叠</a-checkbox
        ></div
      >
      <div class="item"
        ><a-checkbox :model-value="dataNodeAll" @change="nodeAllChanges"
          >全选/全不选</a-checkbox
        ></div
      >
      <div class="item"
        ><a-checkbox
          :model-value="dataCheckStrictly"
          @change="checkStrictlyChanges"
          >父子联动</a-checkbox
        ></div
      >
    </div>
    <div class="data-tree-box-border">
      <a-tree
        :data="treeData"
        :expanded-keys="expandedKeys"
        :checked-keys="checkedKeys"
        :checkable="true"
        :field-names="props.fieldNames"
        :check-strictly="!checkStrictly"
        @expand="treeExpandChange"
        @check="treeCheckChanges"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { ref, watch } from 'vue';
  import { treeToList } from '@/utils/index';
  import { Message } from '@arco-design/web-vue';

  const props = defineProps({
    getData: {
      type: Function,
    },
    idKey: {
      type: String,
      default: 'id',
    },
    fieldNames: {
      type: Object,
      default: () => ({
        key: 'id',
        title: 'label',
        children: 'children',
      }),
    },
    modelValue: {
      type: Object,
      default: () => ({}),
    },
  });
  const emit = defineEmits(['update:modelValue']);
  const dataExpand = ref(false);
  const dataNodeAll = ref(false);
  const dataCheckStrictly = ref(false);
  const expandedKeys: any = ref([]);
  const checkedKeys: any = ref([]);
  const checkStrictly: any = ref(false);
  const treeData = ref([]);

  const expandChange = (value: any) => {
    dataExpand.value = value;
    expandedKeys.value = [];
    if (value) {
      const data = treeToList(treeData.value, { idKey: 'key' });
      expandedKeys.value = data
        .filter((item) => item.children)
        .map((item) => item.key);
    }
  };
  const nodeAllChanges = (value: any) => {
    dataNodeAll.value = value;
    checkedKeys.value = [];
    if (value) {
      const data = treeToList(treeData.value, { idKey: 'key' });
      checkedKeys.value = data.map((item) => item.key);
    }
    emit('update:modelValue', {
      checks: checkedKeys.value,
      checkStrictly: checkStrictly.value,
    });
  };
  const checkStrictlyChanges = (value: any) => {
    dataCheckStrictly.value = value;
    checkStrictly.value = value;
    emit('update:modelValue', {
      checks: checkedKeys.value,
      checkStrictly: checkStrictly.value,
    });
  };

  const treeExpandChange = (expandKeys: any) => {
    expandedKeys.value = expandKeys;
  };
  const treeCheckChanges = (checkKeys: any) => {
    checkedKeys.value = checkKeys;
    emit('update:modelValue', {
      checks: checkedKeys.value,
      checkStrictly: checkStrictly.value,
    });
  };
  watch(
    () => props.modelValue,
    (value) => {
      checkedKeys.value = value.checks;
      checkStrictlyChanges(value.checkStrictly);
    },
    {
      deep: true,
      immediate: true,
    }
  );
  const initTreeData = async () => {
    if (props?.getData) {
      const { code, msg, data } = await props.getData();
      if (code !== 200) {
        Message.error(msg);
      }
      treeData.value = data;
    }
  };
  initTreeData();
</script>

<style lang="less" scoped>
  .data-tree-box {
    &-op {
      display: flex;
      align-items: center;
      .item {
        margin: 0 20px 0 0;
      }
    }
    &-border {
      padding: 10px;
      margin-top: 5px;
      border: 1px solid #e5e6e7;
      background: #ffffff none;
      border-radius: 4px;
    }
  }
</style>
